home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_147 / sys / sysv / sysv.zoo / ttyio.c < prev   
C/C++ Source or Header  |  1988-07-25  |  6KB  |  266 lines

  1. /*
  2.  * Name:    MicroEMACS
  3.  *        System V terminal I/O.
  4.  * Version:    0
  5.  * Last edit:    Tue Aug 26 23:57:57 PDT 1986
  6.  * By:        gonzo!daveb
  7.  *        {sun, amdahl, mtxinu}!rtech!gonzo!daveb
  8.  *
  9.  * The functions in this file
  10.  * negotiate with the operating system for
  11.  * keyboard characters, and write characters to
  12.  * the display in a barely buffered fashion.
  13.  *
  14.  * This version goes along with tty/termcap/tty.c.
  15.  * Terminal size is determined there, rather than here, and
  16.  * this does not open the termcap file
  17.  */
  18. #include    "def.h"
  19.  
  20. #include    <sys/types.h>
  21. #include    <fcntl.h>
  22. #include    <termio.h>
  23.  
  24. #define    NOBUF    512            /* Output buffer size.        */
  25.  
  26. char    obuf[NOBUF];            /* Output buffer.        */
  27. int    nobuf;                /* buffer count            */
  28.  
  29. static struct termio    ot;        /* entry state of the terminal    */
  30. static struct termio    nt;        /* editor's terminal state    */
  31.  
  32. static int ttyactivep = FALSE;        /* terminal in editor mode?    */
  33. static int ttysavedp = FALSE;        /* terminal state saved?    */
  34.  
  35. int    nrow;                /* Terminal size, rows.        */
  36. int    ncol;                /* Terminal size, columns.    */
  37.  
  38. /* These are used to implement typeahead on System V */
  39.  
  40. int kbdflgs;            /* saved keyboard fd flags    */
  41. int kbdpoll;            /* in O_NDELAY mode            */
  42. int kbdqp;            /* there is a char in kbdq    */
  43. char kbdq;            /* char we've already read    */
  44.  
  45. /*
  46.  * This function gets called once, to set up
  47.  * the terminal channel.  This version turns off flow
  48.  * control.  This may be wrong for your system, but no
  49.  * good solution has really been found (daveb).
  50.  */
  51. ttopen()
  52. {
  53.     register char    *cp;
  54.     extern char    *getenv();
  55.  
  56.     if (ttyactivep)
  57.         return;
  58.  
  59.     if( !ttysavedp )
  60.     {
  61.         if (ioctl(0, TCGETA, &ot) < 0)
  62.             abort();
  63.         nt = ot;        /* save entry state        */
  64.         nt.c_cc[VMIN] = 1;    /* one character read is OK    */
  65.         nt.c_cc[VTIME] = 0;    /* Never time out.        */
  66.         nt.c_iflag |= IGNBRK;
  67.         nt.c_iflag &= ~( ICRNL | INLCR | ISTRIP | IXON | IXOFF );
  68.         nt.c_oflag &= ~OPOST;
  69.         nt.c_cflag |= CS8;    /* allow 8th bit on input    */
  70.         nt.c_cflag &= ~PARENB;    /* Don't check parity        */
  71.         nt.c_lflag &= ~( ECHO | ICANON | ISIG );
  72.  
  73.         kbdpoll = (((kbdflgs = fcntl(0, F_GETFL, 0)) & O_NDELAY) != 0);
  74.     
  75.         ttysavedp = TRUE;
  76.     }
  77.     
  78.     if (ioctl(0, TCSETAF, &nt) < 0)
  79.         abort();
  80.  
  81.     /* This really belongs in tty/termcap... */
  82.  
  83.     if ((cp=getenv("TERMCAP")) == NULL
  84.     || (nrow=getvalue(cp, "li")) <= 0
  85.     || (ncol=getvalue(cp, "co")) <= 0) {
  86.         nrow = 24;
  87.         ncol = 80;
  88.     }
  89.     if (nrow > NROW)            /* Don't crash if the    */
  90.         nrow = NROW;            /* termcap entry is    */
  91.     if (ncol > NCOL)            /* too big.        */
  92.         ncol = NCOL;
  93.  
  94.     ttyactivep = TRUE;
  95. }
  96.  
  97. /*
  98.  * This routine scans a string, which is
  99.  * actually the return value of a getenv call for the TERMCAP
  100.  * variable, looking for numeric parameter "name". Return the value
  101.  * if found. Return -1 if not there. Assume that "name" is 2
  102.  * characters long. This limited use of the TERMCAP lets us find
  103.  * out the size of a window on the X display.
  104.  */
  105. getvalue(cp, name)
  106. register char    *cp;
  107. register char    *name;
  108. {
  109.     for (;;) {
  110.         while (*cp!=0 && *cp!=':')
  111.             ++cp;
  112.         if (*cp++ == 0)            /* Not found.        */
  113.             return (-1);
  114.         if (cp[0]==name[0] && cp[1]==name[1] && cp[2]=='#')
  115.             return (atoi(cp+3));    /* Stops on ":".    */
  116.     }
  117. }
  118.  
  119. /*
  120.  * This function gets called just
  121.  * before we go back home to the shell. Put all of
  122.  * the terminal parameters back.
  123.  */
  124. ttclose()
  125. {
  126.     if(!ttysavedp || !ttyactivep)
  127.         return;
  128.     ttflush();
  129.     if (ioctl(0, TCSETAF, &ot) < 0 || fcntl( 0, F_SETFL, kbdflgs ) < 0)
  130.         abort();
  131.     ttyactivep = FALSE;
  132. }
  133.  
  134. /*
  135.  * Write character to the display.
  136.  * Characters are buffered up, to make things
  137.  * a little bit more efficient.
  138.  */
  139. ttputc(c)
  140. {
  141.     if (nobuf >= NOBUF)
  142.         ttflush();
  143.     obuf[nobuf++] = c;
  144. }
  145.  
  146. /*
  147.  * Flush output.
  148.  */
  149. ttflush()
  150. {
  151.     if (nobuf != 0) {
  152.         write(1, obuf, nobuf);
  153.         nobuf = 0;
  154.     }
  155. }
  156.  
  157. /*
  158.  * Read character from terminal.
  159.  * All 8 bits are returned, so that you can use
  160.  * a multi-national terminal.
  161.  *
  162.  * If keyboard 'queue' already has typeahead from a typeahead() call,
  163.  * just return it.  Otherwise, make sure we are in blocking i/o mode
  164.  * and read a character.
  165.  */
  166. ttgetc()
  167. {
  168.     if( kbdqp )
  169.         kbdqp = FALSE;
  170.     else
  171.     {
  172.         if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
  173.             abort();
  174.         kbdpoll = FALSE;
  175.         while (read(0, &kbdq, 1) != 1)
  176.             ;
  177.     }
  178.     return ( kbdq & 0xff );
  179. }
  180.  
  181. /*
  182.  * Return non-FALSE if typeahead is pending.
  183.  *
  184.  * If already got unread typeahead, do nothing.
  185.  * Otherwise, set keyboard to O_NDELAY if not already, and try
  186.  * a one character read.
  187.  */
  188. typeahead()
  189. {
  190.     if( !kbdqp )
  191.     {
  192.         if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 )
  193.             abort();
  194.         kbdpoll = TRUE;
  195.         kbdqp = (1 == read( 0, &kbdq, 1 ));
  196.     }
  197.     return ( kbdqp );
  198. }
  199.  
  200.  
  201. /*
  202.  * panic:  print error and die, leaving core file.
  203.  * Don't know why this is needed (daveb).
  204.  */
  205. panic(s)
  206. char *s;
  207. {
  208.     fprintf(stderr, "%s\r\n", s);
  209.     abort();
  210. }
  211.  
  212.  
  213. /*
  214. ** This should check the size of the window, and reset if needed.
  215. */
  216.  
  217. setttysize()
  218. {
  219. #ifdef    TIOCGWINSZ
  220.     auto struct winsize wsize;
  221.     if (ioctl(0, TIOCGWINSZ, (char *) &wsize) == 0) {
  222.         nrow = wsize . ws_row;
  223.         ncol = wsize . ws_col;
  224.     } else
  225. #endif
  226.     if ((nrow=tgetnum ("li")) <= 0
  227.     || (ncol=tgetnum ("co")) <= 0) {
  228.         nrow = 24;
  229.         ncol = 80;
  230.     }
  231.     if (nrow > NROW)            /* Don't crash if the    */
  232.         nrow = NROW;            /* termcap entry is    */
  233.     if (ncol > NCOL)            /* too big.        */
  234.         ncol = NCOL;
  235. }
  236.  
  237. #ifndef NO_DPROMPT
  238. #include <signal.h>
  239. #include <setjmp.h>
  240.  
  241. static jmp_buf tohere;
  242.  
  243. static alrm()
  244. {
  245.     longjmp(tohere, -1);
  246. }
  247.  
  248. /*
  249.  * Return TRUE if we wait without doing anything, else return FALSE.
  250.  */
  251.  
  252. ttwait()
  253. {
  254.     int alrm();
  255.  
  256.     if (kbdqp)
  257.         return FALSE;        /* already pending input    */
  258.     if (setjmp(tohere))
  259.         return TRUE;        /* timeout on read if here    */
  260.     signal(SIGALRM, alrm); alarm(2);
  261.     kbdqp = (1 == read(0, &kbdq, 1));
  262.     alarm(0);
  263.     return FALSE;            /* successful read if here    */
  264. }
  265. #endif NO_DPROMPT
  266.